/**
 * 个人主页
 */
import React from 'react';

import { Checkbox, Col, Modal, Row, Spin } from 'antd';
import { connect } from 'umi';
import debounce from 'lodash/debounce';

import GuideByServerFlag from '@/components/GuideByServerFlag';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import { withRoutePage } from '@/utils/enhanceUtils';
import { eventTrack } from '@/utils/track';

import DnD from './dnd';
import styles from './homepage.less';
import LayoutModal from './LayoutModal';
import Cylc from './part/Cylc';
import Gzzd from './part/Gzzd';
import HyyXwtp from './part/HyyXwtp';
import Kqrl from './part/Kqrl';
import OnboardAndLeave from './part/OnboardAndLeave';
import Profile from './part/Profile';
import { getDragItemStyle, getItemStyle, getListStyle } from './part/styles';
import Todo from './part/Todo';
import Xwgg from './part/Xwgg';
import Zpgl from './part/Zpgl';
import { move, reorder } from './utils';

const CheckboxGroup = Checkbox.Group;
const EXCLUDE_CODE = ['welcome', 'news'];

const excludeCardNameList = ['shortcuts', 'my_flow_new', 'rule', 'often_flow', 'todo'];

/**
 * 根据服务端下发的模块 code 获取个人主页对应的功能组件
 * @param {Object} responders  custom props
 */
const getComponents = (key, dataSource, responders) => {
    const componentsMap = {
        attendance: <Kqrl responders={responders} />,
        news_bulletin: <Xwgg dataSource={dataSource} responders={responders} />,
        often_flow: <Cylc responders={responders} />,
        recruit: <Zpgl responders={responders} />,
        rule: <Gzzd dataSource={dataSource} responders={responders} />,
        welcome: <HyyXwtp />,
        news: <Profile avatarFile={responders.avatarFile} />,
        transfer: <OnboardAndLeave responders={responders} />,
        my_flow_new: <Todo responders={responders} />
    };
    return componentsMap[key] || null;
};

@withRoutePage
@connect(({ global, homePage, loading, user }) => ({
    global,
    homePage,
    avatarFile: user.avatarFile,
    loading: loading.models.homePage
}))
class HomePage extends React.Component {
    constructor() {
        super();
        this.handleSaveSubmit = debounce(this.handleSaveSubmit, 300);
        this.guideRef = React.createRef();
    }

    state = {
        onBeforeCapture: false, // 拖动之前
        modalVisible: false,
        deleteCode: '',
        checkModules: [],
        originCheckModules: [], // 取消
        initModules: [] // 重置用
    };

    componentDidMount() {
        const { dispatch, global } = this.props;
        dispatch({
            type: 'homePage/init',
            callback: result => {
                const modules = result.map(item => item.code);
                this.setState(
                    {
                        checkModules: modules,
                        originCheckModules: modules
                    },
                    () => {
                        this.initDnD();
                        if (!global.welcomeEnable) {
                            this.guideRef.current.start();
                        }
                    }
                );
            }
        });
        dispatch({
            type: 'homePage/getList'
        });
    }

    componentDidUpdate(prevPros) {
        const {
            homePage: { personalModules }
        } = this.props;
        if (JSON.stringify(prevPros.homePage.personalModules) !== JSON.stringify(personalModules)) {
            this.fixZIndex();
        }
        // welcomeEnable 被更新, fetchQueryEmployeeFlag 这个接口可能请求延时的情况
        if (prevPros.global.welcomeEnable !== this.props.global.welcomeEnable) {
            if (this.props.global.welcomeEnable) {
                this.guideRef.current.stop();
            } else {
                this.guideRef.current.start();
            }
        }
    }

    componentWillUnmount() {
        const { dispatch } = this.props;
        dispatch({
            type: 'homePage/save',
            payload: {
                personalModules: [],
                allModules: []
            }
        });
        DnD.destroy();
    }

    fixZIndex = () => {
        const doms = document.querySelectorAll('.dnd-context .ant-tabs-nav');
        if (doms && doms.length) {
            Array.from(doms).forEach(dom => {
                // eslint-disable-next-line no-param-reassign
                dom.style.zIndex = 902;
            });
        }
    };

    getList = id => {
        const id2List = ['left', 'right'];
        return this.computeList(id2List[id]);
    };

    onDragEnd = result => {
        const { source, destination } = result;
        this.setState({
            onBeforeCapture: false
        });
        // dropped outside the list
        if (destination.dragIndex === -1) {
            return;
        }
        if (source.dropIndex === destination.dropIndex) {
            const left = reorder(this.getList(source.dropIndex), source.dragIndex, destination.dragIndex);
            let pos = 'left';
            let state = { left };
            if (source.dropIndex === 1) {
                state = { right: left };
                pos = 'right';
            }
            this.setDragDorpData(state, pos);
        } else {
            const newResult = move(
                this.getList(source.dropIndex),
                this.getList(destination.dropIndex),
                source,
                destination
            );
            this.setDragDorpData({
                left: newResult[0],
                right: newResult[1]
            });
        }
        this.handleSaveSubmit();
    };

    handleAddModule = () => {
        this.setState({ modalVisible: true });
    };

    // 添加modal中的save
    handleSaveModule = ({ checkBoxes, modules }) => {
        const {
            homePage: { allModules, personalModules },
            dispatch
        } = this.props;

        let checked = [];
        let newAllModules;
        const basePersonalModules = modules || personalModules;

        // 入参可以是checkbox的string array或者是数据接口的object array
        if (checkBoxes) {
            checked = checkBoxes;
            newAllModules = allModules.map(item => ({
                ...item,
                check: checkBoxes.includes(item.code)
            }));
        } else {
            newAllModules = allModules.map(item => ({
                ...item,
                check: modules.some(it => {
                    if (item.code === it.code) {
                        checked.push(it.code);
                        return true;
                    }
                    return false;
                })
            }));
        }

        const newPersonalModules = [];
        newAllModules.forEach(item => {
            if (item.check) {
                const exist = basePersonalModules.find(it => item.code === it.code);
                if (exist) {
                    newPersonalModules.push(exist);
                } else {
                    newPersonalModules.push({
                        position: 'left',
                        code: item.code,
                        sort: newAllModules.length + newPersonalModules.length
                    });
                }
            }
        });
        dispatch({
            type: 'homePage/save',
            payload: {
                personalModules: newPersonalModules,
                allModules: newAllModules
            }
        });
        this.setState(
            {
                modalVisible: false,
                checkModules: checked,
                originCheckModules: checked
            },
            () => {
                this.handleSaveSubmit();
            }
        );
    };

    handleDeleteModule = code => {
        const { checkModules } = this.state;
        let targetCode;
        if (code) {
            targetCode = code;
        } else {
            const { deleteCode } = this.state;
            targetCode = deleteCode;
        }
        const checked = checkModules.filter(item => item !== targetCode);
        this.handleSaveModule({ checkBoxes: checked });
        // this.setState({ deleteModalVisible: false });
    };

    handleSaveSubmit = () => {
        const {
            homePage: { personalModules },
            dispatch
        } = this.props;
        dispatch({
            type: 'homePage/savePersonalModules',
            payload: {
                params: personalModules
            },
            callback: () => {
                this.setState({ initModules: personalModules });
            }
        });
    };

    handleCancelModule = () => {
        const { originCheckModules } = this.state;
        this.setState({
            modalVisible: false,
            checkModules: originCheckModules
        });
    };

    handleReset = () => {
        const { initModules } = this.state;
        this.handleSaveModule({ modules: initModules });
    };

    setDragDorpData = data => {
        const {
            dispatch,
            homePage: { personalModules }
        } = this.props;
        const formatData = [];
        Object.keys(data).forEach(key => {
            data[key].forEach((item, index) => {
                formatData.push({
                    position: key,
                    sort: index + 1,
                    code: item
                });
            });
        });
        const restPersonalModules = personalModules.filter(item => !formatData.some(it => it.code === item.code));

        dispatch({
            type: 'homePage/save',
            payload: {
                personalModules: [...restPersonalModules, ...formatData]
            }
        });
    };

    setCheckModules = checkModules => {
        this.setState({ checkModules });
    };

    // 获取当前key值对应的data，用来传递给子组件数据
    getDataSource = code => {
        const {
            homePage: { dataSource }
        } = this.props;
        const dataMap = {
            news_bulletin: dataSource.noticeList,
            rule: dataSource.ruleList
        };
        return dataMap[code] || [];
    };

    getComponentName = code => {
        const {
            homePage: { allModules }
        } = this.props;

        const existModule = allModules.find(item => item.code === code);
        if (existModule) {
            const excludeResult = excludeCardNameList.find(item => item === existModule.code);
            return excludeResult && !this.state.onBeforeCapture ? null : <span>{existModule.name}</span>;
        }
        return null;
    };

    computeList = pos => {
        const {
            homePage: { personalModules }
        } = this.props;

        const resultPersonalModules = personalModules
            .filter(item => item.position === pos && !EXCLUDE_CODE.includes(item.code))
            .sort((a, b) => a.sort - b.sort)
            .map(item => item.code);
        return [...Array.from(new Set(resultPersonalModules))];
    };

    initDnD() {
        // 渲染后
        DnD.initialize();
        DnD.events.dragEnd = this.onDragEnd;
        DnD.events.promiseDragStart = () =>
            new Promise(resolve => {
                this.setState({ onBeforeCapture: true }, () => {
                    resolve();
                });
            });
    }

    handleUserLayoutChanged(personalModules) {
        this.setState({ initModules: personalModules });
    }

    render() {
        const {
            onBeforeCapture,
            modalVisible,
            checkModules
            // deleteModalVisible
        } = this.state;

        const {
            homePage: { allModules },
            loading
        } = this.props;

        const renderComponentItem = ({ code, listId, style = {} }) => {
            const { avatarFile } = this.props;
            const plusStyle = onBeforeCapture
                ? { height: 0, minHeight: 0, margin: 0, padding: 0, overflow: 'hidden' }
                : style;
            const component = getComponents(code, this.getDataSource(code), {
                droppableProps: { 'data-rbd-droppable-id': listId },
                onDelete: () => {
                    this.handleDeleteModule(code);
                },
                onAdd: () => {
                    if (code === 'news_bulletin') {
                        eventTrack({
                            eventName: 'new_notice_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'rule') {
                        eventTrack({
                            eventName: 'portal_rules_manage_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'attendance') {
                        eventTrack({
                            eventName: 'portal_attendance_calendar_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'transfer') {
                        eventTrack({
                            eventName: 'portal_my_onboard_and_leave_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'my_flow_new') {
                        eventTrack({
                            eventName: 'portal_flow_new_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'recruit') {
                        // eventTrack({
                        //     eventName: 'personal_portal_recruit_addModel_click',
                        //     eventProps: {
                        //         label: '个人主页-我的招聘-添加模块'
                        //     }
                        // });
                    } else if (code === 'shortcuts') {
                        eventTrack({
                            eventName: 'portal_shortcut_add_model_click',
                            pageName: 'personal_portal'
                        });
                    } else if (code === 'often_flow') {
                        eventTrack({
                            eventName: 'portal_common_flow_add_model_click',
                            pageName: 'personal_portal'
                        });
                    }
                    this.handleAddModule();
                },
                avatarFile
            });
            return (
                <div style={{ ...getItemStyle(), ...plusStyle }} className={styles.dragItemContent}>
                    {component}
                </div>
            );
        };

        const renderDragItem = ({ code, title, style = {}, disable = false }) => {
            const plusStyle = !onBeforeCapture ? { boxShadow: 'none' } : style;
            return (
                <div className={disable ? '' : 'dnd-draggable'} style={{ ...getDragItemStyle(), ...plusStyle }}>
                    {title || this.getComponentName(code)}
                </div>
            );
        };

        const renderDragList = (listData, listId) => (
            <div className="dnd-droppable" style={getListStyle()}>
                {listData.map(item => (
                    <div key={item}>
                        {renderDragItem({ code: item })}
                        {renderComponentItem({ code: item, listId, style: { marginTop: '-68px' } })}
                    </div>
                ))}
            </div>
        );
        return (
            <>
                <PageHeaderWrapper>
                    <GuideByServerFlag
                        ref={this.guideRef}
                        manual
                        serverStorageKey="guideHomePage"
                        isShowSkipBtn={false}
                        nextText="下一步"
                        finishText="开启全新 Work"
                    >
                        {/* tab nav 滚动时可见 */}
                        <div className={styles.noUserSelect} style={{ overflowX: 'auto' }}>
                            <Row className="dnd-context" style={{ minWidth: 1200 }}>
                                <Col span={16} style={{ paddingRight: 12 }} data-layout="left">
                                    {onBeforeCapture &&
                                        renderDragItem({
                                            code: 'welcome',
                                            title: '图片新闻',
                                            style: { color: 'rgba(0,0,0,0.45)' },
                                            disable: true
                                        })}
                                    {renderComponentItem({
                                        code: 'welcome',
                                        style: { padding: 0 }
                                    })}
                                    {renderDragList(this.computeList('left'), 'droppable')}
                                </Col>
                                <Col span={8} data-layout="right">
                                    {onBeforeCapture &&
                                        renderDragItem({
                                            code: 'news',
                                            title: '个人信息',
                                            style: { color: 'rgba(0,0,0,0.45)' },
                                            disable: true
                                        })}
                                    {renderComponentItem({
                                        code: 'news'
                                    })}

                                    {renderDragList(this.computeList('right'), 'droppable2')}
                                </Col>
                            </Row>
                        </div>
                    </GuideByServerFlag>
                </PageHeaderWrapper>
                <Modal
                    title="添加桌面模块"
                    width={564}
                    visible={modalVisible}
                    okText="提交"
                    onOk={() => this.handleSaveModule({ checkBoxes: checkModules })}
                    onCancel={() => this.handleCancelModule()}
                    centered
                >
                    <Spin spinning={loading}>
                        <div
                            style={{
                                fontSize: 14,
                                lineHeight: '22px',
                                marginBottom: 19
                            }}
                        >
                            请选择需要添加到个人主页的的模块：
                        </div>
                        <CheckboxGroup
                            options={allModules.map(item => ({
                                label: item.name,
                                value: item.code,
                                disabled: !item.enable
                            }))}
                            value={checkModules}
                            onChange={this.setCheckModules}
                        />
                    </Spin>
                </Modal>
                <LayoutModal />
            </>
        );
    }
}

export default HomePage;
